package com.verify.verifyalism2.controller;

import cn.tass.SRJ1933.devices.constant.TACryptConst;
import cn.tass.SRJ1933.devices.inf.TassSignServerApi;
import cn.tass.SRJ1933.devices.params.response.p7Envelop.DecryptP7EnvelopResponse;
import cn.tass.SRJ1933.devices.params.response.p7Envelop.DecryptP7SignedAndEnvelopResponse;
import cn.tass.SRJ1933.devices.params.response.p7Envelop.P7EnvelopExternalResponse;
import cn.tass.SRJ1933.devices.params.response.p7Envelop.P7SignedAndEnvelopResponse;
import cn.tass.SRJ1933.devices.params.response.p7Sign.P7SignResponse;
import cn.tass.SRJ1933.devices.params.response.p7Sign.VerifyP7SignResponse;
import cn.tass.exceptions.TAException;
import com.verify.verifyalism2.req.VerifyReq;
import com.verify.verifyalism2.res.ResultDTO;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;


@Slf4j
@RestController()
@RequestMapping(value = "/aliProxy")
public class VerifyController {


    private static TassSignServerApi signServerApi;

    private static String printFormat = "错误码[%d]\n错误消息[%s]\n接口结果： %s";

    /**
     * 类加载的时候，只需要初始化一次即可，且可以一直使用，没有时效限制
     */
    static {
        System.out.println("*********** 设备开始初始化... *********** ");
        try {
            String config =
                    "{"
                            + "[LOGGER];"
                            + "logsw=error;logPath=./;"
                            + "[HOST1];"
                            + "hsmModel=SVSM;"
                            + "host=172.16.13.37;"
                            + "port=9081;"
                            + "linkNum=-10;"
                            + "sysname=aly-zcjk;"
                            + "signkey=;"
                            + "}";
            signServerApi = TassSignServerApi.init(config);
            if (null == signServerApi) {
                // 初始化失败
                System.err.println("初始化失败....");
            }
            System.out.println("*********** 设备初始化完成... *********** ");
        } catch (TAException e) {
            System.err.println("初始化失败...");
            e.printStackTrace();
        }
    }






    //加签
    @PostMapping("/p7Sign")
    public ResultDTO<String> p7Sign(@RequestBody VerifyReq verifyReq) {
        String keyId = "aly-zcjk";
        int keyIdType = 0;
        String keyAccessCode = "";
        String algorithm = TACryptConst.TA_S_ALG_SM3WITHSM2;
        int dataType = 0;
        boolean isDetach = true;
        String sm2UserID = "";
        boolean isReturnCertInfo = true;
        int infoType = 1;
        int signCertType = 0;
        P7SignResponse p7SignResponse = null;
        try {
            p7SignResponse = signServerApi.p7Sign(keyId, keyIdType, keyAccessCode, sm2UserID, algorithm, verifyReq.getOriginData(), dataType, isDetach, isReturnCertInfo, infoType, signCertType);
        } catch (TAException e) {
            log.error("调用阿里生成签名接口失败，异常信息为：{}", e.getMessage());
            return ResultDTO.<String>builder().success(false).message("调用阿里生成签名接口失败").build();
        }
        log.info("p7签名(内部密钥)结果为：{}", String.format(printFormat, p7SignResponse.getCode(), p7SignResponse.getMsg(), p7SignResponse.toString()));
        return ResultDTO.<String>builder().success(int2Boolean(p7SignResponse.getCode())).data(p7SignResponse.getSign()).build();
    }

    //加密-不带签名的数字信封
    @PostMapping("/p7EnvelopExternal")
    public ResultDTO<String> p7EnvelopExternal(@RequestBody VerifyReq verifyReq)  {
        //清算所导入服务器对应的公钥证书
        String cert = "MIICuzCCAl6gAwIBAgIFEEYyABEwDAYIKoEcz1UBg3UFADBcMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRswGQYDVQQDDBJDRkNBIFRFU1QgU00yIE9DQTEwHhcNMjEwOTI2MDMwMzA4WhcNMjYwOTI2MDMwMzA4WjByMQswCQYDVQQGEwJjbjEVMBMGA1UECgwMQ0ZDQSBURVNUIENBMQ0wCwYDVQQLDARDSEZNMRkwFwYDVQQLDBBPcmdhbml6YXRpb25hbC0xMSIwIAYDVQQDDBkwNDFAMzEyMzQ1NkBjb21tQDAwMDAwMDAxMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE5WFigL8lA3su9spoX3h7HQcsGm9kfxYT4JZfbSdZ7JcMZaDZmKS1LEbA/KOdF1mPY0UN7ab/tvNhse2Tcl+FiaOB9DCB8TAfBgNVHSMEGDAWgBRr/hjaj0I6prhtsy6Igzo0osEw4TBIBgNVHSAEQTA/MD0GCGCBHIbvKgEBMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2ZjYS5jb20uY24vdXMvdXMtMTQuaHRtMDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly91Y3JsLmNmY2EuY29tLmNuL1NNMi9jcmwyNjIwMC5jcmwwCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBRI4h4qUtluyjSfoXCp/4pHuemLNTAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwDAYIKoEcz1UBg3UFAANJADBGAiEA63Z9OfK4zlkJ4jSAihAwrd6FYvlU7ZUGgf2+pFO4X44CIQDdXuEeWA02js6w1L6UezvNH2hF5QV3PTK1Znylrr3mmQ==";
        String encAlgorithm = TACryptConst.GBSMS4_CBC;
        boolean isReturnCertInfo = true;
        int infoType = 0;
        P7EnvelopExternalResponse p7EnvelopExternalResponse = null;
        try {
            p7EnvelopExternalResponse = signServerApi.p7EnvelopExternal(cert, encAlgorithm, verifyReq.getOriginData(), isReturnCertInfo, infoType);
        } catch (TAException e) {
            log.error("调用阿里生成不带签名的数字信封接口失败，异常信息为:{}", e.getMessage());
            return ResultDTO.<String>builder().success(false).message("调用阿里生成不带签名的数字信封接口失败").build();
        }
        log.info("外部证书制作p7信封:{}", String.format(printFormat, p7EnvelopExternalResponse.getCode(), p7EnvelopExternalResponse.getMsg(), p7EnvelopExternalResponse.toString()));
        return ResultDTO.<String>builder().success(int2Boolean(p7EnvelopExternalResponse.getCode())).data(p7EnvelopExternalResponse.getEnvelop()).build();
    }

    //加密-带签名的数字信封
    @PostMapping("/p7CreateSignedAndEnvelop")
    public ResultDTO<String> p7CreateSignedAndEnvelop(@RequestBody VerifyReq verifyReq)  {
        String signKeyId = "aly-zcjk";
        int signKeyIdType = 0;
        String signKeyAccessCode = "";
        String signAlgorithm = TACryptConst.TA_S_ALG_SM3WITHSM2;
        String encAlgorithm = TACryptConst.GBSMS4_CBC;
        String sm2UserID = "";
        String encCert = "MIICuzCCAl6gAwIBAgIFEEYyABEwDAYIKoEcz1UBg3UFADBcMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRswGQYDVQQDDBJDRkNBIFRFU1QgU00yIE9DQTEwHhcNMjEwOTI2MDMwMzA4WhcNMjYwOTI2MDMwMzA4WjByMQswCQYDVQQGEwJjbjEVMBMGA1UECgwMQ0ZDQSBURVNUIENBMQ0wCwYDVQQLDARDSEZNMRkwFwYDVQQLDBBPcmdhbml6YXRpb25hbC0xMSIwIAYDVQQDDBkwNDFAMzEyMzQ1NkBjb21tQDAwMDAwMDAxMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE5WFigL8lA3su9spoX3h7HQcsGm9kfxYT4JZfbSdZ7JcMZaDZmKS1LEbA/KOdF1mPY0UN7ab/tvNhse2Tcl+FiaOB9DCB8TAfBgNVHSMEGDAWgBRr/hjaj0I6prhtsy6Igzo0osEw4TBIBgNVHSAEQTA/MD0GCGCBHIbvKgEBMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2ZjYS5jb20uY24vdXMvdXMtMTQuaHRtMDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly91Y3JsLmNmY2EuY29tLmNuL1NNMi9jcmwyNjIwMC5jcmwwCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBRI4h4qUtluyjSfoXCp/4pHuemLNTAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwDAYIKoEcz1UBg3UFAANJADBGAiEA63Z9OfK4zlkJ4jSAihAwrd6FYvlU7ZUGgf2+pFO4X44CIQDdXuEeWA02js6w1L6UezvNH2hF5QV3PTK1Znylrr3mmQ==";
        boolean isAttachSign = true;
        int attachSignFormat = 0;
        boolean isReturnCertInfo = true;
        int infoType = 1;
        P7SignedAndEnvelopResponse p7SignedAndEnvelopResponse = null;
        try {
            p7SignedAndEnvelopResponse = signServerApi.p7CreateSignedAndEnvelop(signKeyId, signKeyIdType, signKeyAccessCode, signAlgorithm, encCert, encAlgorithm, verifyReq.getOriginData(), sm2UserID,
                    isAttachSign, attachSignFormat, isReturnCertInfo, infoType);
        } catch (TAException e) {
            log.error("调用阿里生成带签名的数字信封接口失败，异常信息为:{}", e.getMessage());
            return ResultDTO.<String>builder().success(false).message("调用阿里生成带签名的数字信封接口失败").build();
        }
        log.info("编制p7带签名的数字证书 - 签名使用内部密钥，加密使用外部证书:{}", String.format(printFormat, p7SignedAndEnvelopResponse.getCode(), p7SignedAndEnvelopResponse.getMsg(), p7SignedAndEnvelopResponse.toString()));
        return ResultDTO.<String>builder().success(int2Boolean(p7SignedAndEnvelopResponse.getCode())).data(p7SignedAndEnvelopResponse.getEnvelop()).build();
    }


    //验签
    @PostMapping("/verifyP7Sign")
    public ResultDTO<Boolean> verifyP7Sign(@RequestBody VerifyReq verifyReq) {
        int dataType = 0;
        boolean isDetach = true;
        boolean isReturnCertInfo = true;
        int infoType = 1;
        VerifyP7SignResponse verifyP7SignResponse = null;
        try {
            verifyP7SignResponse = signServerApi.verifyP7Sign(verifyReq.getOriginData(), dataType, verifyReq.getSign(), isDetach, isReturnCertInfo, infoType);
        } catch (TAException e) {
            log.error("调用阿里验签接口失败，异常信息为:{}", e.getMessage());
            return ResultDTO.<Boolean>builder().success(false).message("调用阿里验签接口失败").build();
        }
        log.info("验证p7签名:{}", String.format(printFormat, verifyP7SignResponse.getCode(), verifyP7SignResponse.getMsg(), verifyP7SignResponse.toString()));
        return ResultDTO.<Boolean>builder().success(int2Boolean(verifyP7SignResponse.getCode())).data(int2Boolean(verifyP7SignResponse.getCode())).build();
    }


    //解密（数字信封）--不带签名的
    @PostMapping("/decryptP7Envelop")
    public ResultDTO<String> decryptP7Envelop(@RequestBody VerifyReq verifyReq)  {
        String keyId = "aly-zcjk";
        int keyIdType = 0;
        String keyAccessCode = "";
        boolean isReturnCertInfo = true;
        int infoType = 0;
        DecryptP7EnvelopResponse decryptP7EnvelopResponse = null;
        try {
            decryptP7EnvelopResponse = signServerApi.decryptP7Envelop(keyId, keyIdType, keyAccessCode, verifyReq.getEnvelop(), isReturnCertInfo, infoType);
        } catch (TAException e) {
            log.error("调用阿里解密（数字信封）--不带签名的接口失败，异常信息为:{}", e.getMessage());
            return ResultDTO.<String>builder().success(false).message("调用阿里解密（数字信封）--不带签名的接口失败").build();
        }
        log.info("解密p7数字信封--不带签名的结果为:{}", String.format(printFormat, decryptP7EnvelopResponse.getCode(), decryptP7EnvelopResponse.getMsg(), decryptP7EnvelopResponse.toString()));
        return ResultDTO.<String>builder().success(int2Boolean(decryptP7EnvelopResponse.getCode())).data(decryptP7EnvelopResponse.getData()).build();
    }


    //解密（带签名的数字信封）--带签名的
    @PostMapping("/decryptP7SignedAndEnvelop")
    public ResultDTO<String> decryptP7SignedAndEnvelop(@RequestBody VerifyReq verifyReq)  {
        String keyId = "aly-zcjk";
        int keyIdType = 0;
        String keyAccessCode = "";
        String sm2UserID = "";
        int verifyLevel = 0;
        boolean isReturnCert = true;
        boolean isAttachSign = true;
        int attachSignFormat = 0;
        boolean isReturnCertInfo = true;
        int infoType = 0;
        DecryptP7SignedAndEnvelopResponse decryptP7SignedAndEnvelopResponse = null;
        try {
            decryptP7SignedAndEnvelopResponse = signServerApi.decryptP7SignedAndEnvelop(keyId, keyIdType, keyAccessCode, verifyReq.getEnvelop(), sm2UserID, verifyLevel, isReturnCert,
                    isAttachSign, attachSignFormat, isReturnCertInfo, infoType);
        } catch (TAException e) {
            log.error("调用阿里解密P7带签名数字信封 - 内部非对称解密的接口失败，异常信息为:{}", e.getMessage());
            return ResultDTO.<String>builder().success(false).message("调用阿里解密P7带签名数字信封 - 内部非对称解密的接口失败").build();
        }
        log.info("解密P7带签名数字信封 - 内部非对称解密:{}", String.format(printFormat, decryptP7SignedAndEnvelopResponse.getCode(), decryptP7SignedAndEnvelopResponse.getMsg(), decryptP7SignedAndEnvelopResponse.toString()));
        return ResultDTO.<String>builder().success(int2Boolean(decryptP7SignedAndEnvelopResponse.getCode())).data(decryptP7SignedAndEnvelopResponse.getData()).build();
    }



    private boolean int2Boolean(int input){
        if(0 == input)
            return true;
        return false;
    }

    /**
     * 测试nginx配置  postman测试提示ssl有问题，直接浏览器测试
     * @return
     */
    @GetMapping("testNginx")
    public String testNginx(){
        return "success";
    }

    /**
     * 这样也可以接收  只不过字符串内容是个json串
     * @param str
     * @return
     */
    @PostMapping("/testRequestBodyString")
    public String testRequestBodyString(@RequestBody String str){
        log.info("str为{}", str);
        return str;
    }



    @Test
    public void testLomBok(){
        ResultDTO<String> str = ResultDTO.<String>builder().data("我是字符串").code("0").success(true).build();
        ResultDTO<Boolean> bool = ResultDTO.<Boolean>builder().data(Boolean.TRUE).code("10").success(false).build();
        ResultDTO<Double> dou = ResultDTO.<Double>builder().data(2.345d).code("0").success(true).build();

        System.out.println(str);
        System.out.println(bool);
        System.out.println(dou);
    }





}
